#include "CNodo.h"
#include "CasilleroA.h"

const CNodo::Operador CNodo::operadores[] = {CNodo::arriba, CNodo::abajo, CNodo::derecha, CNodo::izquierda};
const CNodo::Operador CNodo::operadoresInv[] = {CNodo::abajo, CNodo::arriba, CNodo::izquierda, CNodo::derecha};

CNodo::CNodo() {

}

//Revisado.

/* copy-constructor para CasilleroA UNICAMENTE*/
CNodo::CNodo(const CNodo& Origen) {
    casillero = new CasilleroA(*(dynamic_cast<CasilleroA*> (Origen.casillero)));
    enlace = Origen.enlace;
    operadorEnlace = Origen.operadorEnlace;
    next = Origen.next;
    previous = Origen.previous;
    g = Origen.g;
    h = Origen.h;
    open = Origen.open;
}

CNodo::CNodo(Casillero *casillero, Operador accion, CNodo *enlace) : next(0), previous(0), g(0), h(0), open(true) {
    this->enlace = enlace;
    this->operadorEnlace = accion;
    this->casillero = casillero;
}

CNodo::~CNodo() {
    delete casillero;
}



//Revisado.

CNodo *CNodo::GenerarSucesor(Operador oper) {
    //retorna un CNodo:
    Casillero *c;

    int tam = Casillas()->Dimenciones();

    switch (oper) { //Si se puede aplicar el operador se
            //crea un nuevo objeto CPuzzle -> el sucesor.
        case izquierda:
            if ((Casillas()->Vacio() % tam) != 0) {
                c = Casillas()->Clone();
                c->moverCero(c->Vacio() - 1);

            } else return NULL;
            break;

        case derecha:
            if ((Casillas()->Vacio() % tam) != (tam - 1)) {
                c = Casillas()->Clone();
                c->moverCero(c->Vacio() + 1);

            } else return NULL;
            break;

        case arriba:
            if (Casillas()->Vacio() >= tam) {
                c = Casillas()->Clone();
                c->moverCero(c->Vacio() - c->Dimenciones());

            } else return NULL;
            break;

        case abajo:
            if (Casillas()->Vacio() < (tam * (tam - 1))) {
                c = Casillas()->Clone();
                c->moverCero(c->Vacio() + c->Dimenciones());

            } else return NULL;
            break;

        default:
            throw new Excepcion("Operador no reconocido en \"CNodo::GenerarSucesor(CNodo suc, Operador oper)\"");
    }

    return new CNodo(c, oper, this);
}


//Revisado.

bool CNodo::EsGoal() {
    short dim = casillero->Dimenciones();
    dim *= dim;
    for (int i = 0; i < dim; i++)
        if (casillero->Info(i) != i)
            return false;
    return true;
}

/*int i;
    for (i = 0; i < Casillas()->Dimenciones() * Casillas()->Dimenciones(); i++)
        if (Casillas()->Info()[i] != i)
            return false;
    return true;*/

